﻿using Modbus.Extensions.Enron;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace PlcTest
{
    public partial class Form1 : Form
    {
        private bool plcIsConnected = false;
        private int sleepTime = 5000;
        private int sleepTime2 = 1000;
        ushort[] plcAddr_barcode = { 3240, 3520, 3920, 5320, 5350, 5380 };//来板顶升
        ushort[] plcAddr_AllowInGrap = { 3008, 3038, 3068, 3098, 3128, 3158 };//上架滚筒位允许抓板
        ushort[] plcAddr_InGraped = { 3039, 3069, 3099, 3099, 3129, 3159 };//上架滚筒位抓板完成
        ushort[] plcAddr_AllowOutPlace = { 3040, 3070, 3100, 3100, 3130, 3160 };//下架滚筒位允许放板
        ushort[] plcAddr_OutPlaced = { 3041, 3071, 3101, 3101, 3131, 3161 };//下架滚筒位放板完成
        ushort[] plcAddr_ShelfPlaced = { 3042, 3072, 3102, 3102, 3132, 3162 };//上架书本架位放板完成
        ushort[] plcAddr_ShelfGraped = { 3043, 3073, 3103, 3103, 3133, 3163 };//下架书本架位抓板完成
        int R = 0;// int.Parse(this.groupBox1.Text.Replace("R", ""));

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            this.comboBox_R.SelectedIndex = R;
        }

        private void button_PlcTestR1_Click(object sender, EventArgs e)
        {
            Button btn = sender as Button;
            string txt = btn.Text;
            #region R1-R6


            try
            {
                if (txt.Contains(plcAddr_barcode[R - 1].ToString()))
                {//来板顶升 5230
                    string barcode = textBox_barcode_r1.Text;
                    if (barcode.Trim() == "")
                    {
                        MessageBox.Show("没有条码");
                        return;
                    }
                    param.nModbustcpnet.WriteMultipleRegisters(plcAddr_barcode[R - 1], param.SetString(0, barcode));
                }
                else if (txt.Contains(plcAddr_AllowInGrap[R - 1].ToString()))
                {//上架允许抓板 3008
                    param.nModbustcpnet.WriteSingleCoil(plcAddr_AllowInGrap[R - 1], true);
                }
                else if (txt.Contains(plcAddr_InGraped[R - 1].ToString()))
                {//上架抓板完成 3009
                    param.nModbustcpnet.WriteSingleCoil(plcAddr_InGraped[R - 1], true);
                    ushort[] empt = new ushort[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0,0,0,0 };
                    param.nModbustcpnet.WriteMultipleRegisters(plcAddr_barcode[R - 1], empt);
                }
                else if (txt.Contains(plcAddr_AllowOutPlace[R - 1].ToString()))
                {//下架允许放板 3010
                    param.nModbustcpnet.WriteSingleCoil(plcAddr_AllowOutPlace[R - 1], true);
                }
                else if (txt.Contains(plcAddr_OutPlaced[R - 1].ToString()))
                {//下架放板完成 3011
                    param.nModbustcpnet.WriteSingleCoil(plcAddr_OutPlaced[R - 1], true);
                }
                else if (txt.Contains(plcAddr_ShelfPlaced[R - 1].ToString()))
                {//书架放板完成 3012
                    param.nModbustcpnet.WriteSingleCoil(plcAddr_ShelfPlaced[R - 1], true);
                }
                else if (txt.Contains(plcAddr_ShelfGraped[R - 1].ToString()))
                {//书架抓板完成 3013
                    param.nModbustcpnet.WriteSingleCoil(plcAddr_ShelfGraped[R - 1], true);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("错误：\n" + ex.Message, "错误");
            }

            #endregion

        }


        /// <summary>
        /// 清除PLC
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_clearPlc_Click(object sender, EventArgs e)
        {
            Button btn = sender as Button;
            string txt = btn.Text.Replace("清空", "");
            try
            {

                ushort[] empt = new ushort[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                bool[] vals = new bool[] { false, false, false, false, false, false };
                param.nModbustcpnet.WriteMultipleRegisters(plcAddr_barcode[R - 1], empt);
                param.nModbustcpnet.WriteMultipleCoils(plcAddr_AllowInGrap[R - 1], vals);
            }
            catch (Exception ex)
            {
                MessageBox.Show("TcpModBus错误：\n" + ex.Message, "错误");
            }


        }

        /// <summary>
        /// 连接PLC
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_tcpConn_Click(object sender, EventArgs e)
        {
            string ip = textBox_ip.Text;
            int port = int.Parse(textBox_port.Text);
            label_tcpStatus.Text = "连接中…";
            Application.DoEvents();
            string cnn = param.TcpModbusConnect(ip, port);
            if (cnn == "OK")
            {
                label_tcpStatus.Text = "已连接";
                plcIsConnected = true;
            }
            else
            {
                label_tcpStatus.Text = "连接失败";
                plcIsConnected = false;
            }
        }

        private void comboBox_R_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.groupBox1.Text = comboBox_R.Text;
            R = int.Parse(this.groupBox1.Text.Replace("R", ""));
            this.button1.Text = string.Format("来板顶升\r\n{0}", plcAddr_barcode[R - 1]);
            this.button2.Text = string.Format("允许上架\r\n{0}", plcAddr_AllowInGrap[R - 1]);
            this.button3.Text = string.Format("上架抓板完成\r\n{0}", plcAddr_InGraped[R - 1]);
            this.button4.Text = string.Format("允许下架\r\n{0}", plcAddr_AllowOutPlace[R - 1]);
            this.button5.Text = string.Format("下架放板完成\r\n{0}", plcAddr_OutPlaced[R - 1]);
            this.button6.Text = string.Format("上架放板完成\r\n{0}", plcAddr_ShelfPlaced[R - 1]);
            this.button7.Text = string.Format("下架抓板完成\r\n{0}", plcAddr_ShelfGraped[R - 1]);
            this.button8.Text = string.Format("清空{0}", this.groupBox1.Text);
        }

        /// <summary>
        /// 导入数据
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_inputData_Click(object sender, EventArgs e)
        {
            this.openFileDialog1.ShowDialog(this);
            string dfile = this.openFileDialog1.FileName;
            if (!string.IsNullOrEmpty(dfile))
            {
                this.dataGridView_data.Rows.Clear();
                using (StreamReader sr = new StreamReader(dfile))
                {
                    string line;
                    string[] dline;
                    int r = 0;
                    while (!sr.EndOfStream)
                    {
                        line = sr.ReadLine();
                        line = line.Trim();
                        if (string.IsNullOrEmpty(line)) { continue; }
                        dline = line.Split('\t');
                        r = this.dataGridView_data.RowCount + 1;
                        this.dataGridView_data.Rows.Add(r, dline[0].Trim(), dline[1].Trim(), "等待中");
                    }
                }
            }
            this.label_rowCount.Text = this.dataGridView_data.RowCount.ToString();
        }

        private void button_clearData_Click(object sender, EventArgs e)
        {
            if (isInputing)
            {
                MessageBox.Show("正在上架中，不能清空，请先停止上架");
                return;
            }
            if (isOutputing)
            {
                MessageBox.Show("正在下架中，不能清空，请先停止下架");
                return;
            }
            this.dataGridView_data.Rows.Clear();
            this.curBarcode = "";
            this.curRowIndex = 0;
            this.curOutNum = 0;
            UpdaStatus("已清空停止");
        }

        #region 批量测试

        private delegate void dlgConnectPlc();
        /// <summary>
        /// 连接PLC
        /// </summary>
        private void ConnectPLC()
        {
            string ip = textBox_ip.Text;
            int port = int.Parse(textBox_port.Text);
            if (this.InvokeRequired)
            {
                Invoke(new dlgConnectPlc(ConnectPLC));
            }
            else
            {
                label_tcpStatus.Text = "连接中…";
                this.label_status.Text = "连接中…";
                string cnn = param.TcpModbusConnect(ip, port);
                if (cnn == "OK")
                {
                    label_tcpStatus.Text = "已连接";
                    plcIsConnected = true;
                }
                else
                {
                    label_tcpStatus.Text = "连接失败";
                    plcIsConnected = false;
                }
            }
        }

        /// <summary>
        /// 上架进程
        /// </summary>
        private Thread thInputStore;

        /// <summary>
        /// 下架进程
        /// </summary>
        private Thread thOutputStore;
        private bool isOutputing = false;
        private bool isInputing = false;

        /// <summary>
        /// 当前板件索引
        /// </summary>
        private int curRowIndex = 0;
        /// <summary>
        /// 当前板件条码
        /// </summary>
        private string curBarcode = "";
        /// <summary>
        /// 当前下板数量
        /// </summary>
        private int curOutNum = 0;

        /// <summary>
        /// 模拟批量上架信号
        /// </summary>
        private void InputStore()
        {
            int rcount = this.dataGridView_data.RowCount;
            int pi = curRowIndex > 0 ? curRowIndex - 1 : 0;
            int reConn = 0;
            bool isErr = false;
            if (rcount > 0)
            {
                while (isInputing && pi < rcount)
                {
                    curRowIndex = pi + 1;
                    curBarcode = this.dataGridView_data.Rows[pi].Cells[2].Value.ToString();
                    if (string.IsNullOrEmpty(curBarcode)) { pi += 1; continue; }
                writeBarcode:
                    //来板顶升位写入条码
                    if (WriteBarcodeToRaiseUp(plcAddr_barcode[R - 1], curBarcode))
                    {
                        reConn = 0;
                        UpdaStatus("已扫描");
                        UpdateDatagrid(pi, 3, "已扫描");
                        UpdateDatagrid(pi, 4, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                        Thread.Sleep(sleepTime);

                    writeGetBoard:
                        //写入上架抓板完成信号
                        if (WriteSingleCoil(plcAddr_InGraped[R - 1], true))
                        {
                            ushort[] empt = new ushort[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
                            param.nModbustcpnet.WriteMultipleRegisters(plcAddr_barcode[R - 1], empt);
                            Thread.Sleep(sleepTime2);
                            param.nModbustcpnet.WriteMultipleRegisters(plcAddr_barcode[R - 1], empt);
                            reConn = 0;
                            UpdaStatus("上架抓板");
                            UpdateDatagrid(pi, 3, "上架抓板完成");
                            //UpdateDatagrid(pi, 4, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                            Thread.Sleep(sleepTime2);

                        writePutBroad:
                            //写入上架放板完成信号
                            if (WriteSingleCoil(plcAddr_ShelfPlaced[R - 1], true))
                            {
                                reConn = 0;
                                UpdaStatus("上架放板完成");
                                UpdateDatagrid(pi, 3, "已入库");
                                UpdateDatagrid(pi, 5, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                                Thread.Sleep(sleepTime2);
                                Thread.Sleep(sleepTime2);
                                pi++;
                            }
                            else
                            {
                                if (reConn < 2)
                                {//失败重连3次
                                    Thread.Sleep(100);
                                    reConn += 1;
                                    UpdaStatus(string.Format("断开重连{0}次", reConn));
                                    ConnectPLC();
                                    goto writePutBroad;
                                }
                                else
                                {
                                    isErr = true;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            if (reConn < 2)
                            {//失败重连3次
                                Thread.Sleep(100);
                                reConn += 1;
                                UpdaStatus(string.Format("断开重连{0}次", reConn));
                                ConnectPLC();
                                goto writeGetBoard;
                            }
                            else
                            {
                                isErr = true;
                                break;
                            }
                        }
                    }
                    else
                    {
                        if (reConn < 2)
                        {//失败重连3次
                            Thread.Sleep(100);
                            reConn += 1;
                            UpdaStatus(string.Format("断开重连{0}次", reConn));
                            ConnectPLC();
                            goto writeBarcode;
                        }
                        else
                        {
                            isErr = true;
                            break;
                        }
                    }
                }
                if (isErr)
                {
                    UpdaStatus("出错中断");
                }
                else
                {
                    if (isInputing) { UpdaStatus("全部上架完成"); } else { UpdaStatus("已中断"); }
                }
                isInputing = false;
                thInputStore.Abort();

            }
            else
            {
                MessageBox.Show("无法执行上架操作！：\n 没有要上架的条码数据,请先导入分拣数据。", "错误");
            }

        }

        /// <summary>
        /// 模拟批量下架信号
        /// </summary>
        private void OutputStore()
        {
            int rcount = this.dataGridView_data.RowCount;
            int pi = 0;
            int reConn = 0;
            bool isErr = false;
            if (rcount > 0)
            {
                //while (isOutputing && curOutNum < curRowIndex) {
                while (pi < rcount)
                {
                writeGetBoard:
                    //写入下架抓板完成信号
                    if (WriteSingleCoil(plcAddr_ShelfGraped[R - 1], true))
                    {
                        reConn = 0;
                        UpdaStatus("下架抓板");
                        Thread.Sleep(sleepTime);

                    writePutBroad:
                        //写入下架放板完成信号
                        if (WriteSingleCoil(plcAddr_OutPlaced[R - 1], true))
                        {
                            curOutNum++;
                            reConn = 0;
                            UpdaStatus("下架放板完成");
                            Thread.Sleep(sleepTime);
                            pi++;
                        }
                        else
                        {
                            if (reConn < 2)
                            {//失败重连3次
                                Thread.Sleep(100);
                                reConn += 1;
                                UpdaStatus(string.Format("断开重连{0}次", reConn));
                                ConnectPLC();
                                goto writePutBroad;
                            }
                            else
                            {
                                isErr = true;
                                break;
                            }
                        }
                    }
                    else
                    {
                        if (reConn < 2)
                        {//失败重连3次
                            Thread.Sleep(100);
                            reConn += 1;
                            UpdaStatus(string.Format("断开重连{0}次", reConn));
                            ConnectPLC();
                            goto writeGetBoard;
                        }
                        else
                        {
                            isErr = true;
                            break;
                        }
                    }
                }
                if (isErr)
                {
                    UpdaStatus("出错中断");
                }
                else
                {
                    if (isOutputing) { UpdaStatus("全部上架完成"); } else { UpdaStatus("已中断"); }
                }
                isOutputing = false;
                thOutputStore.Abort();
            }
            else
            {
                MessageBox.Show("无法执行下架操作！：\n 没有下架的条码数据。", "错误");
            }

        }


        /// <summary>
        /// 写入条码到来板顶升位
        /// </summary>
        /// <param name="barcode">条码</param>
        /// <param name="addr">地址码</param>
        /// <returns></returns>
        private bool WriteBarcodeToRaiseUp(ushort addr, string barcode)
        {
            try
            {
                param.nModbustcpnet.WriteMultipleRegisters(addr, param.SetString(0, barcode));
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        private bool WriteSingleCoil(ushort addr, bool value = false)
        {
            try
            {
                param.nModbustcpnet.WriteSingleCoil(addr, value);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }


        private delegate void dlgUpdateStatus(string status);
        /// <summary>
        ///  更新状态
        /// </summary>
        /// <param name="status"></param>
        private void UpdaStatus(string status)
        {
            if (this.InvokeRequired)
            {
                Invoke(new dlgUpdateStatus(UpdaStatus), status);
            }
            else
            {
                this.label_status.Text = status;
                this.label_curBarcode.Text = this.curBarcode;
                this.label_curIndex.Text = this.curRowIndex.ToString();
                this.label_OutNum.Text = this.curOutNum.ToString();
            }
        }

        private delegate void dlgUpdateDatagrid(int row, int col, object value);
        /// <summary>
        /// 更新列表单元数据
        /// </summary>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <param name="value"></param>
        private void UpdateDatagrid(int row, int col, object value)
        {
            if (this.InvokeRequired)
            {
                Invoke(new dlgUpdateDatagrid(UpdateDatagrid), row, col, value);
            }
            else
            {
                this.dataGridView_data.Rows[row].Selected = true;
                this.dataGridView_data.CurrentCell = this.dataGridView_data.Rows[row].Cells[col];
                this.dataGridView_data.Rows[row].Cells[col].Value = value;

            }
        }




        #endregion

        /// <summary>
        /// 模拟批量来板上架信号
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_startInstore_Click(object sender, EventArgs e)
        {
            isInputing = true;
            thInputStore = new Thread(InputStore);
            thInputStore.IsBackground = true;
            thInputStore.Start();
        }

        /// <summary>
        /// 停止 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_Stop_Click(object sender, EventArgs e)
        {
            isOutputing = false;
            isInputing = false;
        }

        /// <summary>
        /// 模拟批量下架信号
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button_startOutstore_Click(object sender, EventArgs e)
        {
            isOutputing = true;
            thOutputStore = new Thread(OutputStore);
            thOutputStore.IsBackground = true;
            thOutputStore.Start();
        }

        private void dataGridView_data_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            string barcode = this.dataGridView_data.Rows[e.RowIndex].Cells[1].Value.ToString();
            this.textBox_barcode_r1.Text = barcode;
        }

        private void textBox_sleep_TextChanged(object sender, EventArgs e)
        {
            int sleep = int.Parse(this.textBox_sleep.Text);
            if (sleep < 500) { sleep = 500; }
            sleepTime = sleep;
        }

        private void button_ScanReceid1_Click(object sender, EventArgs e)
        {
            param.nModbustcpnet.WriteSingleCoil(3200, true);
        }

        private void button_ScanReceid2_Click(object sender, EventArgs e)
        {
            param.nModbustcpnet.WriteSingleCoil(3201, true);
        }

        private void button9_Click(object sender, EventArgs e)
        {
            try
            {
                ushort[] registersLen = new ushort[2];
                registersLen[0] = (ushort)(2210 >> 16);    // 高16位
                registersLen[1] = (ushort)(2210 & 0xFFFF); // 低16位
                param.nModbustcpnet.WriteMultipleRegisters(3010, registersLen);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"{ex}");
            }
           

        }

        private void button10_Click(object sender, EventArgs e)
        {
            try
            {
                param.nModbustcpnet.WriteSingleRegister(3010, Convert.ToUInt16(2210));
            }
            catch (Exception ex)
            {
                MessageBox.Show($"{ex}");
            }
        }

        private void button11_Click(object sender, EventArgs e)
        {
            try
            {
                string barcode = textBox_barcode_r1.Text;
                if (barcode.Trim() == "")
                {
                    MessageBox.Show("没有条码");
                    return;
                }
                param.nModbustcpnet.WriteMultipleRegisters(3000, param.SetString(0, barcode));
                Thread.Sleep(1000);
                param.nModbustcpnet.WriteSingleCoil(3020, true);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"{ex}");
            }
        }
    }
}
